package com.specter.utils;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Enumeration;

import org.apache.commons.lang3.StringUtils;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;

/**
 * Note:地址工具类
 * 
 * @author Liang.Wang
 * @version Apr 20, 2011 4:46:15 PM
 */
@Slf4j
public class URLUtils {

	private URLUtils() {
	}

	/**
	 * 把当前请求的参数一并传到下一页面
	 * 
	 * @param request
	 * @param postfix
	 * @return
	 */
	public static String constructURL(HttpServletRequest request, String postfix) {
		String url = request.getRequestURL().toString();
		// String path = request.getServletPath();可能导致未空
		String path = getRelativePath(request);

		String prefix = StringUtils.substringBefore(url, path);
		String suffix = request.getQueryString();
		String go = prefix + postfix;
		if (suffix != null && !"".equals(suffix)) {
			String andStr;
			if (postfix.contains("?")) {
				andStr = "&";
			} else {
				andStr = "?";
			}
			go = go + andStr + suffix;
		}
		return go;
	}

	/**
	 * 只做重定向的跳转，忽略当前参数
	 * 
	 * @param request
	 * @param postfix
	 * @return
	 */
	public static String constructRedirectURL(HttpServletRequest request, String postfix) {
		String url = request.getRequestURL().toString();
		// String path = request.getServletPath();可能导致未空
		String path = getRelativePath(request);

		String prefix = StringUtils.substringBefore(url, path);
		if (prefix.endsWith("/") && postfix.startsWith("/")) {
			postfix = postfix.substring(1);
		}
		return prefix + postfix;
	}

	/**
	 * 获取当前请求的
	 * 
	 * @param request
	 * @return
	 */
	public static String getRequestCTX(HttpServletRequest request) {
		String url = request.getRequestURL().toString();
		// String path = request.getServletPath();可能导致未空
		String path = getRelativePath(request);

		String prefix = StringUtils.substringBefore(url, path);
		return StringUtils.removeEnd(prefix, "/");
	}

	/**
	 * 获得当前请求的地址，包括参数
	 * 
	 * @param request
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static String getRequestURL(HttpServletRequest request) {

		// String path = request.getServletPath();可能导致未空
		String path = getRelativePath(request);

		Enumeration e = request.getParameterNames();
		StringBuilder sb = new StringBuilder();
		while (e.hasMoreElements()) {
			String name = (String) e.nextElement();
			String[] values = request.getParameterValues(name);
			for (String value : values) {

				try {
					value = URLEncoder.encode(value, "UTF-8");
				} catch (UnsupportedEncodingException e1) {
					e1.printStackTrace();
				}

				if (sb.length() != 0) {
					sb.append("&");
				}
				sb.append(name);
				sb.append("=");
				sb.append(value);
			}
		}

		if (StringUtils.isNotBlank(sb.toString())) {
			path = path + "?" + sb.toString();
		}
		return path;
	}

	/**
	 * 获得当前请求的地址，只包含指定的参数，用逗号(,)分隔
	 * 
	 * @param request
	 * @param parameters
	 * @return url
	 */
	public static String getRequestURL(HttpServletRequest request, String parameters) {
		// String path = request.getServletPath();可能导致未空
		String path = getRelativePath(request);

		if (StringUtils.isNotBlank(parameters)) {
			String[] ps = StringUtils.split(parameters, ",");
			StringBuffer sb = new StringBuffer();
			for (String p : ps) {
				String paramValue = request.getParameter(p);
				if (StringUtils.isNotBlank(paramValue)) {
					sb.append(p);
					sb.append("=");
					sb.append(paramValue);
					sb.append("&");
				}
			}

			if (StringUtils.isNotBlank(sb.toString())) {
				sb.deleteCharAt(sb.length() - 1);
				path = path + "?" + sb.toString();
			}
		}
		return path;
	}

	/**
	 * 获取相对与项目名的路径获取相对与项目名的路径
	 * 
	 * @param request
	 * @return
	 */
	public static String getRelativePath(HttpServletRequest request) {
		String uri = request.getRequestURI();
		String contextPath = request.getContextPath();
		if (contextPath != null && contextPath.length() > 0) {
			uri = uri.substring(contextPath.length());
		}
		return uri;
	}

	/**
	 * 获取用户真实IP地址，不使用request.getRemoteAddr()的原因是有可能用户使用了代理软件方式避免真实IP地址,
	 * 可是，如果通过了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP值
	 * 
	 * @return ip
	 */
	public static String getRemoteAddr(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		String unknown = "unknown";
		if (StringUtils.isBlank(ip) || unknown.equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (StringUtils.isBlank(ip) || unknown.equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (StringUtils.isBlank(ip) || unknown.equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_CLIENT_IP");
		}
		if (StringUtils.isBlank(ip) || unknown.equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
		}
		if (StringUtils.isBlank(ip) || unknown.equalsIgnoreCase(ip)) {
			ip = request.getHeader("X-Real-IP");
		}
		if (StringUtils.isBlank(ip) || unknown.equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		if (StringUtils.isNotBlank(ip) && !unknown.equalsIgnoreCase(ip)) {
			// 多次反向代理后会有多个ip值，第一个ip才是真实ip
			ip = ip.contains(",") ? StringUtils.substringBefore(ip, ",") : ip;
		}
		if (ip.equals("0:0:0:0:0:0:0:1") || ip.equalsIgnoreCase("localhost")) {
			ip = "127.0.0.1";
		}
		if (log.isDebugEnabled()) {
			log.debug("The client real ip is: " + ip);
		}
		return ip;
	}

	/**
	 * 对地址栏进行编码
	 * 
	 * @param input       输入字符串
	 * @param charsetName 字符集
	 * @return 编码后的字符串
	 */
	public static String encode(String input, String charsetName) {
		String result = input;
		try {
			result = URLEncoder.encode(input, charsetName);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 对地址栏进行解码
	 * 
	 * @param input       输入字符串
	 * @param charsetName 字符集
	 * @return 解码后的字符串
	 */
	public static String decode(String input, String charsetName) {
		String result = input;
		try {
			result = URLDecoder.decode(input, charsetName);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 检验ip是否符合规则
	 * 
	 * @param ip 待检地址
	 * @param rx 校验规则
	 * @return 是否符合
	 */
	public static boolean ipMatch(String ip, String rx) {
		String[] ips = ip.split("\\.");
		String[] rxs = rx.split("\\.");
		for (int i = 0; i < ips.length; i++) {
			if (!rxs[i].equals("*") && !rxs[i].equals(ips[i])) {
				return false;
			}
		}
		return true;
	}

}
